﻿// MIT License
// 开源地址：https://gitee.com/co1024/AbcMvc
// Copyright (c) 2021-2023 1024
// Abc.Mvc=Furion+EF+SqlSugar+Pear layui admin.

using Abc.Core.SeedData;
using Furion.DynamicApiController;
using System.Text;

namespace Abc.Application.HtAdminServices;

/// <summary>
/// 开发服务
/// </summary>
public class HtDeveloperService : IDeveloperService, ITransient
{
    private readonly ILogger<HtDeveloperService> _logger;

    private readonly ISqlSugarClient _db;
    private readonly IDataConfigService _dataConfigService;
    public HtDeveloperService(ILogger<HtDeveloperService> logger
    , ISqlSugarClient db,
IDataConfigService dataConfigService)
    {
        _logger = logger;
        _db = db;
        _dataConfigService = dataConfigService;
    }

    #region 更新菜单功能权限

    /// <summary>
    /// 更新菜单功能权限
    /// </summary>
    /// <returns></returns>
    [UnitOfWork]
    public async Task UpdateMenuPermission(bool isThrowEx = true)
    {
        var _logger = AppEx.GetSeriLogger("Abc\\菜单生成更新");
        var sbLog = new StringBuilder();
        try
        {
            //查询自动生成的菜单
            var newMenus = AuthorityHelper.GetMenuPermissions();
            sbLog.AppendLine($"获取到当前的菜单权限数为：{newMenus.Count}");

            var entityNames = newMenus.Select(o => o.EntityType).Distinct().ToList();
            //添加默认的菜单表 SysMenu
            var sysMenuType = typeof(SysMenu);
            if (!entityNames.Any(o => o == sysMenuType)) entityNames.Add(sysMenuType);

            //设置菜单默认的实体类
            foreach (var menu in newMenus)
            {
                if (menu.EntityType == null) menu.EntityType = sysMenuType;
            }

            foreach (var entityType in entityNames)
            {
                if (entityType == null) continue;
                await UpdateMenuPermission(newMenus, entityType, sbLog, isThrowEx);
            }
        }
        catch (Exception ex)
        {
            sbLog.AppendLine(ex.ToStringEx());
            _logger.Error(sbLog.ToString());
        }
        finally
        {
            _logger.Debug(sbLog.ToString());
        }
    }

    private async Task UpdateMenuPermission(List<MaMenuItem> sourceMenus, Type entityType, StringBuilder sbLog, bool isThrowEx = true)
    {
        var newMenus = sourceMenus.Where(o => o.EntityType == entityType).ToList();
        sbLog.AppendLine($"获取到当前的菜单权限数为：{newMenus.Count}");

        //var tableName = SqlSugarHelper.GetTableNameByAllDb(entityName, _db);

        //var type = Type.GetType($"Abc.Core.Entities.{entityName}");

        //var a = _db.Ado.Connection.Database.getta

        var entityInfo = _db.GetEntityInfoByAllDb(entityType);

        //获取数据库中全部的菜单和权限
        var dbmenus = await _db.Queryable<SysMenu>().AS(entityInfo.DbTableName).ToListAsync();
        sbLog.AppendLine($"数据库中菜单权限数为：{dbmenus.Count}");

        //需要新增到数据库中的菜单/功能
        var AddMenus = new List<SysMenu>();

        var DeleteMenus = new List<SysMenu>();
        // 移除 数据库中不存在的MVC 菜单
        RemoveDbNotData(newMenus, dbmenus, DeleteMenus);

        //新增或更新 菜单与权限
        AddOrUpdateMenu(newMenus, dbmenus, AddMenus);

        //获取菜单目录
        foreach (var menu in SysMenuSeedData.GetData())
        {
            if (dbmenus.Any(o => o.Code.Trim().ToLower() == menu.Code.Trim().ToLower())) continue;
            menu.Id = 0;
            AddMenus.Add(menu);
        }

        foreach (var addmenu in AddMenus)
        {
            addmenu.IsAutoGeneration = true;
        }

        //验证Code 是否有重复
        var AddMenus2 = new List<SysMenu>();
        foreach (var menu in AddMenus)
        {
            if (AddMenus2.Any(o => o.MenuAreaType == menu.MenuAreaType && o.Area == menu.Area && o.Code.Trim().ToLower() == menu.Code.Trim().ToLower()))
            {
                if (isThrowEx)
                {
                    sbLog.AppendLine($"菜单权限验重 Code:{menu.Code} 数据：{menu.ToJson()}");

                    throw Oops.Bah(errorMessage: $"Code：{menu.Code} 重复，请检查!!");
                }
            }
            else
            {
                AddMenus2.Add(menu);
            }
        }

        //处理父级菜单/顶级菜单
        HandleParentMenu(dbmenus, AddMenus2);

        var deleteMenuIds = DeleteMenus.Select(o => o.Id).ToList();
        //删除不存在的数据
        await _db.Deleteable<object>().AS(entityInfo.DbTableName).Where("id in (@id) ", new { id = DeleteMenus.Select(o => o.Id).ToArray() }).ExecuteCommandAsync();
        sbLog.AppendLine($"删除菜单：{deleteMenuIds.Count()}");
        //新增菜单数据
        await _db.Insertable(AddMenus2).AS(entityInfo.DbTableName).ExecuteReturnSnowflakeIdListAsync();
        sbLog.AppendLine($"新增菜单：{AddMenus2.Count()}");

        //更新菜单
        //await _db.Storageable(dbmenus).SplitUpdate(o => o.Item.Id > 0).ExecuteCommandAsync();
        var updateCount = await _db.Updateable(dbmenus).AS(entityInfo.DbTableName).ExecuteCommandAsync();
    }

    /// <summary>
    /// 处理菜单 父级菜单目录
    /// </summary>
    /// <param name="dbmenus"></param>
    /// <param name="addMenus"></param>
    private void HandleParentMenu(List<SysMenu> dbmenus, List<SysMenu> addMenus)
    {
        var parentMenus = new List<SysMenu>();
        foreach (MenuAreaType menuAreaType in Enum.GetValues(typeof(MenuAreaType)))
        {
            var areas = addMenus.Where(o => o.MenuAreaType == menuAreaType).Select(o => o.Area).Distinct();
            foreach (var area in areas)
            {
                //判断数据库中是否已经存在
                if (dbmenus.Any(o => o.MenuAreaType == menuAreaType && !string.IsNullOrWhiteSpace(o.Area) && o.Area.ToLower() == area.ToLower() && o.Code.ToLower() == area.ToLower()))
                {
                    continue;
                }
                var menu = new SysMenu
                {
                    MenuAreaType = menuAreaType,
                    Area = area.Trim(),
                    Code = area.Trim(),
                    Name = area.Trim(),
                    IsEnable = true,
                    IsSystem = true,
                    IsShow = true,
                    MenuType = MenuType.目录
                };
                parentMenus.Add(menu);
            }
        }

        addMenus.AddRange(parentMenus);
    }

    /// <summary>
    /// 移除数据库中不存在的数据
    /// </summary>
    /// <param name="menuItems"></param>
    /// <param name="dbmenus"></param>
    /// <param name="deleteMenus"></param>
    private void RemoveDbNotData(List<MaMenuItem> menuItems, List<SysMenu> dbmenus, List<SysMenu> deleteMenus)
    {
        foreach (MenuAreaType menuAreaType in Enum.GetValues(typeof(MenuAreaType)))
        {
            //var dbmenus2 = dbmenus.Where(o =>o.MenuAreaType== menuAreaType && o.IsAutoGeneration);
            //生成的所有Code
            var dic = menuItems.Where(o => o.MenuAreaType == menuAreaType).Select(o => o.Code).Distinct().ToDictionary(k => k, v => v);
            //foreach (var menuitem in menuItems)
            //{
            //    if (dic.ContainsKeyIgnoreCase(menuitem.Code))
            //    {
            //        foreach (var item in menuitem.Permissions)
            //        {
            //            if (dic.ContainsKeyIgnoreCase(item.Code)) continue;
            //            dic.Add(item.Code, item.Code);
            //        }
            //    }
            //    else
            //    {
            //        dic.Add(menuitem.Code, menuitem.Code);
            //        foreach (var item in menuitem.Permissions)
            //        {
            //            if (dic.ContainsKeyIgnoreCase(item.Code)) continue;
            //            dic.Add(item.Code, item.Code);
            //        }
            //    }
            //}

            //遍历移除数据库中所有生成的不存在的菜单数据
            foreach (var menuid in dbmenus.Where(o => o.MenuAreaType == menuAreaType && o.IsAutoGeneration).Select(o => o.Id).ToList())
            {
                var dbmenu = dbmenus.First(o => o.Id == menuid);
                if (string.IsNullOrWhiteSpace(dbmenu.Code)) continue;

                if (!dic.ContainsKeyIgnoreCase(dbmenu.Code))
                {
                    deleteMenus.Add(dbmenu);
                }
            }
        }
    }

    /// <summary>
    /// 新增或更新菜单、功能
    /// </summary>
    /// <param name="menuItems"></param>
    /// <param name="dbmenus"></param>
    /// <param name="addMenus"></param>
    private void AddOrUpdateMenu(List<MaMenuItem> menuItems, List<SysMenu> dbmenus, List<SysMenu> addMenus)
    {
        foreach (var menuitem in menuItems)
        {
            var dbmenu = dbmenus.FirstOrDefault(o => o.MenuAreaType == menuitem.MenuAreaType && o.Area == menuitem.Area && o.Code.Trim().ToLower() == menuitem.Code.Trim().ToLower());
            if (dbmenu == null)
            {
                dbmenu = menuitem.Adapt<SysMenu>();
                dbmenu.IsEnable = true;
                dbmenu.OpenType = 0;
                dbmenu.IsShow = true;
                //menu.MenuType = MenuType.菜单;
                if (!string.IsNullOrWhiteSpace(menuitem.CreateDate))
                {
                    dbmenu.CreationTime = Convert.ToDateTime(menuitem.CreateDate);
                }
                addMenus.Add(dbmenu);
            }
            else
            {
                //菜单已存在，
                {
                    if (string.IsNullOrWhiteSpace(menuitem.PCode))
                    {
                        dbmenu.PCode = menuitem.PCode;
                    }
                    dbmenu.Area = menuitem.Area;
                    dbmenu.Name = menuitem.Name;
                    dbmenu.Url = menuitem.Url;
                    dbmenu.IsDisuse = menuitem.IsDisuse;
                    dbmenu.PCode = menuitem.PCode;
                    dbmenu.IsShow = menuitem.IsShow;
                    dbmenu.MenuType = menuitem.MenuType;
                }
            }
        }
    }

    /// <summary>
    /// 删除数据库所有菜单
    /// </summary>
    /// <returns></returns>
    public async Task DeleteDbAllMenu()
    {
        await _db.Deleteable<SysRoleMenu>().Where(o => o.MenuId > 0).ExecuteCommandAsync();
        await _db.Deleteable<SysMenu>().Where(o => o.Id > 0).ExecuteCommandAsync();
    }

    #endregion 更新菜单功能权限

    /// <summary>
    /// RSA 加密解密验证
    /// </summary>
    /// <param name="publicKey">公钥</param>
    /// <param name="privateeKey">私钥</param>
    /// <returns></returns>
    public bool RsaVer(string publicKey, string privateeKey)
    {
        var LoginPriveKey = privateeKey.Replace("\r\n", "").Replace("\r", "").Replace("\n", "").RsaKeyFilter();
        var LoginPublicKey = publicKey.Replace("\r\n", "").Replace("\r", "").Replace("\n", "").RsaKeyFilter();
        LoginRsa rsa = new LoginRsa(LoginPriveKey, LoginPublicKey);
        //加密
        var enstr = rsa.Encrypt(publicKey);

        //解密
        var pwdtxt = rsa.Decrypt(enstr);

        return true;
    }

    /// <summary>
    /// 生成模板代码
    /// </summary>
    /// <param name="config"></param>
    public void GenerateCode(CG_CodeGenerateConfig config)
    {
        CodeGenerateHelper.GenerateCode(config);
    }

    /// <summary>
    /// 数据库差异对比
    /// </summary>
    /// <param name="config">数据库配置</param>
    /// <returns></returns>
    public string DbDifferenceTables(SqlSugarDbTableConfig config)
    {
        var result = "";
        if (!string.IsNullOrWhiteSpace(config.DbConn))
        {
            result = "数据库类型和数据库里连接字符串都设置了，使用设置的对比\r\n" + SqlSugarHelper.DifferenceTables(config);
        }
        else
        {
            result = "使用默认数据库对比\r\n" + SqlSugarHelper.DifferenceTables();
        }

        return result;
    }

    /// <summary>
    /// 更新数据库表
    /// </summary>
    /// <returns></returns>
    public string InitTables(SqlSugarDbTableConfig config)
    {
        SqlSugarHelper.InitTables(config);


        return "更新成功";
    }

    /// <summary>
    /// 创建数据库
    /// </summary>
    /// <param name="config">数据库配置</param>
    /// <returns></returns>
    public string CreateDb(SqlSugarDbTableConfig config)
    {
        return SqlSugarHelper.CreateDb(config);
    }

    /// <summary>
    /// 保存数据库配置
    /// </summary>
    /// <param name="config"></param>
    /// <returns></returns>
    public string SaveDbConfig(SqlSugarDbTableConfig config)
    {
        _dataConfigService.AddOrUpdateSetting(config, SysDataConfigKey.SqlSugarDbTableConfig).GetAwaiter().GetResult();

        return "保存成功";
    }

    /// <summary>
    /// 更新数据种子
    /// </summary>
    /// <param name="config">数据库配置</param>
    /// <returns></returns>
    public string UpdateDataSeed(SqlSugarDbTableConfig config)
    {
        var state = SqlSugarHelper.UpdateDataSeed(config);
        return state ? "更新成功" : "更新失败";
    }
}